//    Copyright (C) Kherty.  All rights reserved.
using System;
using OpenLS.Spreadsheet.Extensibility;

namespace OpenLS.Spreadsheet.StandardAddIn
{
    /// <summary>
    /// Contains the spreadsheet functions in the information category.
    /// </summary>
    [AddInFunctions]
    public static class InformationFunctions
    {
        public static object Cell([CellContextAttribute] ICell context, string info_type,
                                  [Optional(null), AcceptsRangeFirstCell] ICell reference)
        {
            if (reference == null)
                reference = context;
            return reference.Info(info_type);
        }

        [AddInFunction(Name = "ERROR.TYPE")]
        public static object Error_Type(object value)
        {
            var e = value as Error;
            if (e != null)
            {
                switch (e.Type)
                {
                    case ErrorType.Null:
                        return 1;
                    case ErrorType.Div0:
                        return 2;
                    case ErrorType.Value:
                        return 3;
                    case ErrorType.Ref:
                        return 4;
                    case ErrorType.Name:
                        return 5;
                    case ErrorType.Num:
                        return 6;
                    case ErrorType.NA:
                        return 7;
                }
            }
            return Errors.NaError;
        }

        public static object Info([WorksheetContext] IWorksheet worksheet, string type_text)
        {
            return worksheet.Info(type_text);
        }

        public static bool IsBlank([AccessCellValue(Force = true, AcceptNull =  true)] object s)
        {
            return s == null;
        }

        public static bool IsErr(params object[] value)
        {
            if (value.Length != 1)
                return true;
            foreach (object o in value)
                if (o is Error)
                {
                    var error = (Error) o;
                    if (error.Type != ErrorType.NA)
                        return true;
                }
            return false;
        }

        public static bool IsError(object value)
        {
            if (value is ICell)
                value = ((ICell) value).Value;
            if (value is IArray)
            {
                IArray array = (IArray) value;
                foreach (var val in array)
                    if (val is Error)
                        return true;
            }
            return value is Error;
        }

        public static bool IsLogical(object s)
        {
            return s is bool;
        }

        public static bool IsNa(object s)
        {
            var e = s as Error;
            if (e == null)
                return false;
            return e.Type == ErrorType.NA;
        }

        public static bool IsNonText(object value)
        {
            return !IsText(value);
        }

        public static bool IsNumber(object s)
        {
            return s is double || s is DateTime;
        }

        public static bool IsRef([NoCellAccess] object value)
        {
            return value is ICell || value is IRange;
        }

        public static bool IsText(object value)
        {
            return value is string;
        }

        public static object N([WorksheetContext] IWorksheet worksheet, object s)
        {
            if (s is double)
                return s;
            if (s is DateTime)
                return worksheet.ChangeType<double>((DateTime) s);
            if (s is bool)
            {
                var b = (bool) s;
                if (b)
                    return 1;
                return 0;
            }
            if (s is Error)
                return s;
            return 0;
        }

        public static Error NA()
        {
            return Errors.NaError;
        }

        public static int Type([AccessCellValue(Force = true)] object value)
        {
            if (value is ICell)
                value = ((ICell) value).Value;
            if (value == null)
                return 1;
            if (value is double || value is DateTime)
                return 1;
            if (value is string)
                return 2;
            if (value is bool)
                return 4;
            if (value is Error)
                return 16;
            if (value is IArray || value is Array)
                return 64;
            throw new NotSupportedException();
        }
    }
}